#include "stdafx.h"
#ifdef WIN32  
#include "include/head.h"
#include "include/imagerecog.h"
#else
#include "head.h"
#include "imagerecog.h"
#endif

void ImageRecog::ClearVertical(Mat &img,int start,int end)
{
	if(start < 0) start = 0;
	if(end < 0 ) end = 0;	
	if(end > img.cols) end = img.cols;
	if(start > end) start = end;

	for (int j = 0; j < img.rows; j++)
	{
		uchar * p = img.ptr<uchar>(j);
		for(int i = start; i < end; i++)//去除两边黑线
		{
			*(p + i) = 255;
		}
	}
}

void ImageRecog::ClearHorizontal(Mat &img,int start,int end)
{
	if(start < 0) start = 0;
	if(end < 0) end = 0;
	if(end > img.rows) end = img.rows;
	if(start > end) start = end;

	for(int i = start; i < end; i++)
	{	
		uchar * p = img.ptr<uchar>(i);
		for (int j = 0; j < img.cols; j++)
		{
			*(p + j) = 255;
		}
	}
}


/*空值返回0，非空返回1
 * 0 填空
 * 1 简答
 * 2 老版简答
 * 3 带题干填空
 * 4 语文作文
 * 5 解答题
 * */
int ImageRecog::IsBlank(const char * path,const char *fileType)
{
	if(fileType == NULL) return -2;
	Mat img = imread(path,0);
	if(!img.data) return -2;

	const int width = img.cols;
	const int height = img.rows;
	Rect rc;
	rc.x = 0;
	rc.y = 0;
	rc.width = width;
	rc.height = height;
	//string filename = GetFilename(path);
	int type = 0;
	if(width < 1300)// 填空题
	{
		rc.width -= 125;//去掉判分区域
		type = 0;
	//	continue; //test
	}
	else if(width >= 1300 && width < 1450)//带题干填空，简答、写作
	{
		Mat imgClone = img.clone();
		int deltHigh = GetRectHigh(imgClone);
		rc.y += deltHigh+5;
		rc.height -= deltHigh+5;
		type = 1; //简答
		if (deltHigh == 0 && rc.height < 800)
		{
			rc.width -= 100;
			type = 3;//带题干的填空
		}
		//if (type == 1) continue; //test
	}
	else if(width >= 1450)//老版简答
	{
		type = 2;
		if(height < 1500)
		{
			rc.x += 220; 
			rc.width -= 220;
		}
	}
	if(rc.width < 0 || rc.height<0 || rc.x+rc.width > width || rc.y+rc.height >height) //小图片判非空
		return 1;

	Mat src = img(rc).clone();
	ClearBlank(src,type);
	if(strlen(fileType)>=1)
	{
		if (fileType[0] == 'I') //语文作文
		{
			type = 4;
			//return 1;
		}
		if(type == 1 && fileType[0]=='C') //C1一题多空，特殊处理
		{
			type = 0;
			ClearVertical(src,0,100);
			ClearVertical(src,0.75*width,width);
		}
		if(type == 1 && fileType[0]=='E')
		{
			type = 5;
		}
	}
	if(JudgeBlank(src,type))
	{
#ifdef WIN32
		imwrite("D:\\test\\1src.jpg",src);
#endif
		return 1;
	}
	else
	{
#ifdef WIN32
		imwrite("D:\\test\\0src.jpg",src);
#endif
		return 0;
	}
		//img.release();

}

/*void ImageRecog::getFiles( string path, vector<string>& files )  
{  
	//文件句柄  
	long   hFile   =   0;  
	//文件信息  
	struct _finddata_t fileinfo;  
	string p;  
	if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) !=  -1)  
	{  
		do  
		{  
			//如果是目录,迭代之  
			//如果不是,加入列表  
			if((fileinfo.attrib &  _A_SUBDIR))  
			{  
				if(strcmp(fileinfo.name,".") != 0  &&  strcmp(fileinfo.name,"..") != 0)  
					getFiles( p.assign(path).append("\\").append(fileinfo.name), files );  
			}  
			else  
			{  
				files.push_back(p.assign(path).append("\\").append(fileinfo.name) );  
			}  
		}while(_findnext(hFile, &fileinfo)  == 0);  
		_findclose(hFile);  
	}  
}*/
/*
string GetFilename(const string fullpathname) 
{ 
	int name_len = fullpathname.length();  
	while(fullpathname[--name_len] != '\\');
	string name="";
	for(int i = name_len+1; i <(int) fullpathname.length(); i++)
	{
		name += fullpathname[i];
	}
	return name; 
} */


int ImageRecog::GetRectHigh(Mat &img)
{
	threshold(img,img,190,255,THRESH_BINARY_INV);
	Rect rc;
	rc.x = 90;
	rc.y =  0;
	rc.height = 100;
	rc.width = img.cols-180;
	vector<vector<cv::Point> > contours;
	vector<Vec4i> hierarchy;  // 分层表示
	Mat src = img(rc);
	findContours(src.clone(), contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
	for (int i = 0; i <(int) contours.size(); i++)
	{
		cv::Rect rect = boundingRect(contours[i]);
		if(rect.width > 0.7*img.cols && rect.height > 20)
		{
			vector<Point> approx;
			approxPolyDP(contours[i], approx, 200, true);//近似
			rect = boundingRect(approx);
			return rect.y+rect.height;
			//rectangle(img,rect,Scalar(128),2);
			break;
		}
	}
	return 0;
}

bool IsRectCross(Rect a, Rect b)
{
	if ((a.x > b.x && a.x < b.x + b.width) || (a.x + a.width > b.x && a.x + a.width < b.x + b.width))
		return true;
	return false;
}

bool ImageRecog::JudgeBlank(Mat &src,int type)
{
	Mat img = src.clone();
	ClearBlank2(img, type);

	threshold(img,img,220,255,THRESH_BINARY_INV);
	if(type == 0)
	{
		Sobel(img,img, CV_8U, 5, 0, 7);
		Mat element = getStructuringElement(MORPH_RECT, Size(10, 1)); 
		dilate(img,img,element);
	}
	else if (type == 3)
	{
		Mat element = getStructuringElement(MORPH_RECT, Size(2, 2));
		erode(img, img, element);
		dilate(img, img, element);
	}
	else if(type == 4)
	{
		Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
		erode(img, img, element,cv::Point(-1,-1),2);
		dilate(img, img, element,cv::Point(-1,-1),1);
	}
	else 
	{	
		Sobel(img,img, CV_8U, 5, 0, 7);
		Mat element = getStructuringElement(MORPH_RECT, Size(12, 1)); 
		dilate(img,img,element);
	}
#ifdef WIN32
	imwrite("D:\\test\\img.jpg",img);
#endif
	vector<vector<cv::Point> > contours;
	vector<Vec4i> hierarchy;  // 分层表示
	findContours(img.clone(), contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
	bool findBlank = false;
	Rect blank;

	for (int i = 0; i < (int)contours.size(); i++)
	{
		if(type == 0 )
		{
			Rect rc = boundingRect(contours[i]);
			if(rc.height > 20)
			{
				rectangle(src,rc,Scalar(128));
				return true;
			}
		}
		else if (type == 3)
		{
			Rect rc = boundingRect(contours[i]);
			if (rc.height > 1000)
				continue;
			if (rc.width > 70 && rc.width < 90 && rc.height < 8)
			{
				rectangle(src, rc, Scalar(125),2);
				findBlank = true;
				blank = rc;
				blank.x += 5;
				blank.width -= 10;
			}
			if (findBlank)
			{
				for (int j = 0; j <(int) contours.size(); j++)
				{
					Rect tmp = boundingRect(contours[j]);
					if ((IsRectCross(tmp, blank) || IsRectCross(blank, tmp)) && tmp.y + tmp.height < blank.y && tmp.y + tmp.height > blank.y-25)
					{
						rectangle(src, tmp, Scalar(125),2);
						findBlank = false;
						break;
					}
				}
			}
			if (findBlank) return false;
		}
		else if(type == 4)
		{
			Rect rc = boundingRect(contours[i]);
			if(rc.height >= 10 && rc.width >= 10 && rc.y > 50)
			{
				rectangle(src, rc, Scalar(125));
				return true;
			}
		}
		else 
		{
			Rect rc = boundingRect(contours[i]);
			if (rc.height > 1300)
				continue;
			
			int standHeight = 37;
			if (img.rows < 80)
			{
				standHeight = 30;
			}
			if (rc.height > standHeight && rc.width > 27)
			{
				if (type == 1 || type == 5)
				{
					if (rc.width > 0.5*src.cols || rc.height >200 || (rc.x<200 && rc.height>35))//宽度过宽，过高，位置处于前200像素之内的肯定是
					{
						rectangle(src, rc, Scalar(125),2);
						return true;
					}
					if (rc.x > 0.5*src.cols && rc.width < 120) continue;//右半部分大多是判分和干扰区
					if (type == 5 && rc.y < 25 && rc.x <200 && src.rows > 400 && rc.height <120) continue;//解答题 忽略题干过高的部分
					if (type == 5 && rc.y < 40 && rc.x > 200 && src.rows > 400 && rc.height <120) continue;//解答题 忽略题干过高的部分
					if (rc.y > 0.5*src.rows && rc.x+rc.width < 55) continue;//左下的横线
					if (rc.y > 0.5*src.rows && rc.x+rc.width > 0.5 *src.cols ) continue;//左下的横线
				}
				rectangle(src, rc, Scalar(125));
				return true;
			}

		}
		
	}
	if (type == 3 && !findBlank) return true;
	return false;
}

void ImageRecog::ClearBlank(Mat &img, int type)
{
	if(type == 0) //去掉左上角题号
	{
		for(int i = 0; i < min(50,img.rows); i++)
		{
			uchar * p = img.ptr<uchar>(i);
			for (int j = 0; j < min(65,img.cols); j++)
				*(p + j) = 255;
		}
	}
	//左边黑线
	for(int i = 0; i < img.rows; i++)//去除两边黑线
	{
		uchar * p = img.ptr<uchar>(i);
		if (type == 0)
		{
			for (int j = 0; j < min(25,img.cols); j++)
				*(p + j) = 255;
		}
		else
		{
			for (int j = 0; j < min(25,img.cols); j++)
				*(p + j) = 255;
		}
	}
	//右边黑线
	if (type == 2)
	{
		for (int i = 0; i < img.rows; i++)
		{
			uchar * p = img.ptr<uchar>(i);
			int j = img.cols - 32;
			if(j < 0) j = 0;
			for (; j < img.cols; j++)
				*(p + j) = 255;
		}
	}
	else
	{
		for (int i = 0; i < img.rows; i++)
		{
			uchar * p = img.ptr<uchar>(i);
			int j = img.cols - 32;
			if(j < 0) j = 0;
			for (; j < img.cols; j++)
				*(p + j) = 255;
		}
	}
	//去除上面黑线
	if (type == 2)
	{
		for (int i = 0; i < min(30,img.rows); i++)
		{
			uchar * p = img.ptr<uchar>(i);
			for (int j = 0; j < img.cols; j++)
				*(p + j) = 255;
		}
	}
	//去除底部黑线
	if(type == 1 || type == 2)
	{
		if(img.rows > 90)
		{
			for(int i = img.rows-25; i < img.rows; i++)
			{
				uchar * p = img.ptr<uchar>(i);
				for(int j = 0; j < img.cols; j++)
					*(p+j) = 255;
			}
		}
	}
	else 
	{
		int i = img.rows-6;
		if(i < 0) i = 0;
		for(; i < img.rows; i++)
		{
			uchar * p = img.ptr<uchar>(i);
			for(int j = 0; j < img.cols; j++)
				*(p+j) = 255;
		}
	}
}

void ImageRecog::ClearBlank2(Mat &img, int type)
{
	//右边黑线
	if (type == 2)
	{
		for (int i = 0; i < img.rows; i++)
		{
			uchar * p = img.ptr<uchar>(i);
			int j = img.cols - 100;
			if(j < 0) j = 0;
			for (int j = img.cols - 100; j < img.cols; j++)
				*(p + j) = 255;
		}
	}
}

//#define WRITE

void ImageRecog::RecogFilesDebug()
{/*
	int size = files.size();  
	for (int i = 0;i < size;i++)  
	{
		Mat img = imread(files[i],0);
		//string filename = GetFilename(files[i]);
		Mat src = img.clone();
		int width = img.cols;
		//int height = img.rows;
		bool ret = false;
		if(width < 1300)// 填空题
		{
			ret = JudgeBlank(img,0);
		}
		else if(width >= 1300 && width < 1450)//带题干填空，简答、写作
		{
			ret = JudgeBlank(img,1);
		}
		else if(width >= 1450)//老版简答
		{
			ret = JudgeBlank(img,2);
		}
#ifdef WRITE
		if(ret)
		{
			stringstream ss;
			ss << "E:\\a\\"<<filename;
			imwrite(ss.str(),src);
		}
		else
		{
			stringstream ss;
			ss << "E:\\b\\"<<filename;
			imwrite(ss.str(),src);
		}
#else	
		imshow("0",img);
		cout<<"ret="<<ret<<endl;
		waitKey(0);
		img.release();
#endif
		
	}
*/
}



void ImageRecog::RecogFiles()
{
/*	int size = files.size();  
	for (int i = 0;i < size;i++)  
	{
		Mat img = imread(files[i],0);
		int width = img.cols;
		int height = img.rows;
		Rect rc;
		rc.x = 0;
		rc.y = 0;
		rc.width = width;
		rc.height = height;
		string filename = GetFilename(files[i]);
		int type = 0;
		if(width < 1300)// 填空题
		{
			rc.width -= 125;//去掉判分区域
			type = 0;
		//	continue; //test
		}
		else if(width >= 1300 && width < 1450)//带题干填空，简答、写作
		{
			Mat imgClone = img.clone();
			int deltHigh = GetRectHigh(imgClone);
			rc.y += deltHigh+5;
			rc.height -= deltHigh+5;
			type = 1; //简答
			if (deltHigh == 0 && rc.height < 800)
			{
				rc.width -= 100;
				type = 3;//带题干的填空
			}
			//if (type == 1) continue; //test
		}
		else if(width >= 1450)//老版简答
		{
			type = 2;
			if(height < 1500)
			{
				rc.x += 220; 
				rc.width -= 220;
			}
			else
			{
				type = 4;//未作答的作文
			}
			
		}
		Mat src = img(rc).clone();
		ClearBlank(src,type);
		stringstream ss;
		if (type == 4)
		{
			ss << "E:\\b\\" << type << "_" << filename;
			imwrite(ss.str(), src);
			continue;
		}
		if(JudgeBlank(src,type))
		{
			ss <<"E:\\a\\"<<type<<"_"<<filename;
			imwrite(ss.str(),src);
		}
		else
		{
			ss << "E:\\b\\"<< type << "_"<<filename;
			imwrite(ss.str(),src);
		}
		//img.release();
	}
*/
}
